iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 24
0
Modern Web

我或許沒那麼懂 Web系列 第 24

Cloud Firestore β (16): Transactions

  • 分享至 

  • xImage
  •  

今天來研究怎麼在 Cloud Firestore 進行 Transactions 吧。先把相關的 API 列出來:

  • firebase.firestore.Firestore
    • runTransaction(updateFunction) returns Promise
      • updateFunction(non-null firebase.firestore.Transaction)
  • firebase.firestore.Transaction
    • set(documentRef, data, options) returns firebase.firestore.Transaction
    • get(documentRef) returns Promise containing non-null firebase.firestore.DocumentSnapshot
    • update(documentRef, ...var_args) returns firebase.firestore.Transaction
    • delete(documentRef) returns firebase.firestore.Transaction

在這裡以要為一個城市的人口增加 10000 為例。首先,我們要透過 runTransaction() 方法執行一個 transactions。在這個方法的參數放的就是想要以 transation 執行的內容所構成的匿名函式,這個函式會得到一個 Transaction 物件,我們就可以透過這個物件提供的 set()get()update()delete() 去操作 Document Reference 物件,這些方法的參數和Document Reference 物件的同名方法相同,只是會插入 Document Reference 物件作為第一個餐數。

當我們發現這個城市不存在於資料庫時就會丟出例外,並且在 runTransaction()回傳的 Promise 物件的 catch() 方法中進行處理;若是所有敘述都成功執行,就會跑到runTransaction()回傳的 Promise 物件的 then() 方法中進行。

let cityRef = db.collection('cities').doc('taichung')

db.runTransaction((transaction) => {
  return transaction.get(cityRef).then(citySnapshot => {
    if (!citySnapshot.exists) {
      throw 'Document does not exist!'
    }

    let increment = 10000
    let population = citySnapshot.get('population') + increment
    transaction.update(cityRef, { population: population })
  })
}).then(function() {
  console.log('Transaction successfully committed!')
}).catch(function(error) {
  console.log('Transaction failed: ', error)
})

因為 transaction 可能會衝突存在導致執行超過一次,為了避免 concurrency 的問題,極度不建議在 transaction 中修改 App 的資訊,而是透過將想修改的資訊傳到 transaction 外部後載進行修改。

若是想要將 transaction 內的資訊傳到外部,可以善用 returnthrowPromise.resolve()Promise.reject()2 等方法將資訊往外傳,如下例:

let cityRef = db.collection('cities').doc('taichung')

db.runTransaction((transaction) => {
  return transaction.get(cityRef).then(citySnapshot => {
    if (!citySnapshot.exists) {
      throw 'Document does not exist!'
    }

    let increment = 10000
    let newPopulation = citySnapshot.get('population') + increment

    if (newPopulation <= 1000000) {
      transaction.update(cityRef, { population: newPopulation })
      return Promise.resolve('Population increased to ' + newPopulation)
    } else {
      return Promise.reject('Sorry! Population is too big.')
    }
  })
}).then(result => {
  // Output: Transaction success: Population increased to 110000
  console.log('Transaction success', result)
}).catch(error => {
  // Output: Transaction failed: Sorry! Population is too big.
  console.log('Transaction failed: ', error)
})

上一篇
Cloud Firestore β (15): 進階查詢 - 2
下一篇
Cloud Firestore β (17): Batch
系列文
我或許沒那麼懂 Web31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言